﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using thesebas;
using thesebas.memcache;
using thesebas.socks5proxy;
using System.Threading;
using thesebas.memcache.monitor;
using System.Text.RegularExpressions;
using System.IO;

namespace testMC
{
    class Program
    {

        static void testUnserialize()
        {
            string[] strings = new string[]{
"s:13:\"abceąsmkljgl\";", //string
"i:122;", //int
"N;", //null
"b:1;", //boolT
"b:0;", //boolF
"i:-12234;", //negint
"d:10.5555555555555553581825733999721705913543701171875;", //float
"d:-355.09090909090906507117324508726596832275390625;", //nfloat
"d:1.11E+7;", //efloat
"a:2:{i:0;s:13:\"abceąsmkljgl\";i:122;d:10.5555555555555553581825733999721705913543701171875;}", //array
"s:2:\"XX\";", //class
"O:8:\"stdClass\":2:{s:6:\"fieldA\";s:13:\"abceąsmkljgl\";s:6:\"fieldB\";a:2:{i:0;s:13:\"abceąsmkljgl\";i:122;d:10.5555555555555553581825733999721705913543701171875;}}", //stdobj
"O:2:\"XX\":4:{s:3:\"pub\";s:10:\"wartoscPub\";s:7:\"\0*\0prot\";s:11:\"wartoscProt\";s:8:\"\0XX\0priv\";s:15:\"wartoscPrywatna\";s:3:\"var\";s:10:\"wartoscVar\";}", //classObj
"O:2:\"YY\":8:{s:4:\"puby\";s:10:\"wartoscPub\";s:8:\"\0*\0proty\";s:11:\"wartoscProt\";s:9:\"\0YY\0privy\";s:15:\"wartoscPrywatna\";s:4:\"vary\";O:8:\"stdClass\":2:{s:6:\"fieldA\";s:13:\"abceąsmkljgl\";s:6:\"fieldB\";a:2:{i:0;s:13:\"abceąsmkljgl\";i:122;d:10.5555555555555553581825733999721705913543701171875;}}s:3:\"pub\";s:10:\"wartoscPub\";s:7:\"\0*\0prot\";s:11:\"wartoscProt\";s:8:\"\0XX\0priv\";s:15:\"wartoscPrywatna\";s:3:\"var\";O:2:\"XX\":4:{s:3:\"pub\";s:10:\"wartoscPub\";s:7:\"\0*\0prot\";s:11:\"wartoscProt\";s:8:\"\0XX\0priv\";s:15:\"wartoscPrywatna\";s:3:\"var\";s:10:\"wartoscVar\";}}", //derivedClassObj

            };

            foreach (string str in strings)
            {
                thesebas.php.PHPVariable v = thesebas.php.serialization.PHPUnserializer.Unserialize(str);
                Console.WriteLine(v);
            }

            Console.ReadLine();
        }

        static void testMC()
        {
            //thesebas.memcache.MemcacheClient mc = new thesebas.memcache.MemcacheClient(IPAddress.Loopback, 11219);
            //mc.connect();
            //thesebas.memcache.StatsBasic bs = mc.BasicStats();
            //Console.WriteLine("Time: {0}, Uptime Since: {1}", bs.Time, bs.UpTimeSince);
            //Console.WriteLine(bs);
            //try
            //{
            //    thesebas.memcache.StatsMalloc ms = mc.MallocStats();
            //    Console.WriteLine(ms);
            //}
            //catch (Exception)
            //{
            //    Console.WriteLine("stats malloc not supported");
            //}
            ////mc.FlushAll();
            //MemcacheItem item = new MemcacheItem();
            //item.data = Encoding.UTF8.GetBytes("to jestem ja!żółć się śłóńći");
            //item.Key = "k1";
            //Console.WriteLine("replace(failed): {0}", mc.Replace(item, 9999));

            //Console.WriteLine("set: {0}", mc.Set(item, 9999));
            //Console.WriteLine("add(failed): {0}", mc.Add(item, 9999));

            //Console.WriteLine("replace: {0}", mc.Replace(item, 9999));
            //item.Key = "k2";

            //Console.WriteLine("add: {0}", mc.Add(item, 9999));

            //try
            //{
            //    Console.WriteLine("set: {0}", mc.Append(item));
            //}
            //catch (Exception e)
            //{
            //    Console.WriteLine(e.Message);
            //}
            //try
            //{
            //    Console.WriteLine("set: {0}", mc.Prepend(item));
            //}
            //catch (Exception e)
            //{
            //    Console.WriteLine(e.Message);
            //}

            //Console.WriteLine("items k1, k2, k3():");
            //MemcacheItem[] items = mc.Get("k1 k2 k3");
            //foreach (MemcacheItem i in items)
            //{
            //    Console.WriteLine(i);
            //}
            //Console.WriteLine("end");

            //Console.WriteLine(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(1243781839).ToLocalTime());
            Console.ReadLine();
        }
        static void Main(string[] args)
        {
            Console.WindowWidth = 160;
            Console.Title = "mcmonitor";
            if (args.Length < 1)
            {
                Program.usage();
                return;
            }
            if (!File.Exists(args[0]))
            {
                Console.WriteLine("file {0} not found", args[0]);
                Program.usage();
            }


            string[] mcs = File.ReadAllLines(args[0]);

            MemcacheMonitorManager man = new MemcacheMonitorManager();

            foreach (string s in mcs)
            {
                Match match = Regex.Match(s, @"(?<host>[^:]+):(?<port>\d+)(?<proxy>@(?<phost>[^:]+):(?<pport>\d+))?(\s+#(?<name>.+))?", RegexOptions.Compiled | RegexOptions.IgnoreCase);
                if (match.Success)
                {

                    MemcacheClient mc = new MemcacheClient();
                    if (match.Groups["proxy"].Success)
                    {
                        Console.WriteLine("connecting to \"{4}\" {0}:{1}  @proxy {2}:{3}", match.Groups["host"].Value, match.Groups["port"].Value, match.Groups["phost"].Value, match.Groups["pport"].Value, match.Groups["name"].Success ? match.Groups["name"].Value : "");
                        Proxy proxy = new Proxy(IPAddress.Parse(match.Groups["phost"].Value), int.Parse(match.Groups["pport"].Value));
                        mc.connect(proxy.ConnectTcpClient(IPAddress.Parse(match.Groups["host"].Value), int.Parse(match.Groups["port"].Value)));
                    }
                    else
                    {
                        Console.WriteLine("connecting to \"{2}\" {0}:{1}", match.Groups["host"].Value, match.Groups["port"].Value, match.Groups["name"].Success ? match.Groups["name"].Value : "");
                        mc.connect(IPAddress.Parse(match.Groups["host"].Value), int.Parse(match.Groups["port"].Value));
                    }
                    man.AddMonitor(new MemcacheMonitor(mc)).Name = match.Groups["name"].Success ? match.Groups["name"].Value : "";
                }
            }

            man.DataReady += new MemcacheMonitorManager.DataReadyDelegate(man_DataReady);
            Console.WriteLine("press any key to continue");
            Console.ReadLine();
            man.StartMonitoring();
            Console.WriteLine("press any key to finish");
            Console.ReadKey();
            Console.WriteLine("finishing");
            man.StopMonitoring();
            Console.WriteLine("finished");
        }

        private static void usage()
        {
            Console.WriteLine("usage: mcmonitor memcaches-list.txt");
        }

        static void man_DataReady(MemcacheMonitorManager manager)
        {
            Console.Clear();
            Console.WriteLine("{0,20}   {1,15}|{2,15}|{3,15}|{4,15}|{5,8}|{6,15}|{7,15}",
                "memcache",
                "Reads KB/s",
                "Writes KB/s",
                "Gets/s",
                "Hits/s",
                "Hits acc",
                "Sets/s",
                "Usage % (KB)"
                );
            foreach (MemcacheMonitor mon in manager.monitors)
            {
                StatsDynamicBasic d = mon.GetBasicStats();
                Console.WriteLine("{0,-20} : {1,15}|{2,15}|{3,15}|{4,15}|{5,8}|{6,15}|{7,15}",
                   String.Format("{0} ({1:0}MB)", mon.Name, d.Newer.LimitMaxBytes / 1024 / 1024),
                    String.Format("{0:0.00}({1:0.00})", d.BytesRead / 1024, d.Newer.BytesReadPerSecond / 1024),
                    String.Format("{0:0.00}({1:0.00})", d.BytesWritten / 1024, d.Newer.BytesWrittenPerSecond / 1024),
                    String.Format("{0:0.0}({1:0.0})", d.Gets, d.Newer.GetsPerSecond),
                    String.Format("{0:0.0}({1:0.0})", d.Hits, d.Newer.HitsPerSecond),
                    String.Format(" {0:0.0}% ", d.Newer.HitsAccuracy * 100),
                    String.Format("{0:0.0}({1:0.0})", d.Sets, d.Newer.SetsPerSecond),
                    String.Format(" {0:0.0}% ({1:0})", d.Newer.Usage * 100, (float)d.Newer.Bytes / 1024)

                    //String.Format("{0}({1})", d.Evictions, d.Newer.EvictionsPerSecond)
                );
            }
        }
    }
}
